{
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:13.471160Z",
          "start_time": "2025-01-17T02:43:10.546185Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4E8yhwI2hjMO",
        "outputId": "ed0d5413-324e-4977-c7d0-e661ea5846c8"
      },
      "source": [
        "import matplotlib as mpl\n",
        "import matplotlib.pyplot as plt\n",
        "%matplotlib inline\n",
        "import numpy as np\n",
        "import sklearn\n",
        "import pandas as pd\n",
        "import os\n",
        "import sys\n",
        "import time\n",
        "from tqdm.auto import tqdm\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.nn.functional as F\n",
        "\n",
        "print(sys.version_info)\n",
        "for module in mpl, np, pd, sklearn, torch:\n",
        "    print(module.__name__, module.__version__)\n",
        "\n",
        "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
        "print(device)\n"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "sys.version_info(major=3, minor=11, micro=11, releaselevel='final', serial=0)\n",
            "matplotlib 3.10.0\n",
            "numpy 1.26.4\n",
            "pandas 2.2.2\n",
            "sklearn 1.6.0\n",
            "torch 2.5.1+cu121\n",
            "cuda:0\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0jzEUTjNhjMQ"
      },
      "source": [
        "## 加载数据"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:14.579109Z",
          "start_time": "2025-01-17T02:43:13.471160Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ocOmyR5nhjMS",
        "outputId": "0291e5c7-e3f6-476d-e028-a330a06bfc9c"
      },
      "source": [
        "from torchvision import datasets\n",
        "from torchvision.transforms import ToTensor\n",
        "\n",
        "# fashion_mnist图像分类数据集\n",
        "train_ds = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=True,\n",
        "    download=True,\n",
        "    transform=ToTensor()\n",
        ")\n",
        "\n",
        "test_ds = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=False,\n",
        "    download=True,\n",
        "    transform=ToTensor()\n",
        ")\n",
        "\n",
        "# torchvision 数据集里没有提供训练集和验证集的划分\n",
        "# 当然也可以用 torch.utils.data.Dataset 实现人为划分\n",
        "# 从数据集到dataloader\n",
        "train_loader = torch.utils.data.DataLoader(train_ds, batch_size=16, shuffle=True)\n",
        "val_loader = torch.utils.data.DataLoader(test_ds, batch_size=16, shuffle=False)"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to data/FashionMNIST/raw/train-images-idx3-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 26.4M/26.4M [00:02<00:00, 10.9MB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/train-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw/train-labels-idx1-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 29.5k/29.5k [00:00<00:00, 197kB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 4.42M/4.42M [00:01<00:00, 3.75MB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 5.15k/5.15k [00:00<00:00, 11.1MB/s]"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 2
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:14.582870Z",
          "start_time": "2025-01-17T02:43:14.579109Z"
        },
        "id": "nfqejyRdhjMS"
      },
      "source": [
        "from torchvision.transforms import Normalize\n",
        "\n",
        "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
        "def cal_mean_std(ds):\n",
        "    mean = 0.\n",
        "    std = 0.\n",
        "    for img, _ in ds:\n",
        "        mean += img.mean(dim=(1, 2))\n",
        "        std += img.std(dim=(1, 2))\n",
        "    mean /= len(ds)\n",
        "    std /= len(ds)\n",
        "    return mean, std\n",
        "\n",
        "\n",
        "# print(cal_mean_std(train_ds))\n",
        "# 0.2860， 0.3205\n",
        "transforms = nn.Sequential(\n",
        "    Normalize([0.2860], [0.3205])\n",
        ")\n"
      ],
      "outputs": [],
      "execution_count": 3
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zPlkUl56hjMT"
      },
      "source": [
        "## 定义模型\n",
        "\n",
        "这里我们没有用`nn.Linear`的默认初始化，而是采用了xavier均匀分布去初始化全连接层的权重\n",
        "\n",
        "xavier初始化出自论文 《Understanding the difficulty of training deep feedforward neural networks》，适用于使用`tanh`和`sigmoid`激活函数的方法。当然，我们这里的模型采用的是`relu`激活函数，采用He初始化（何凯明初始化）会更加合适。感兴趣的同学可以自己动手修改并比对效果。\n",
        "\n",
        "|神经网络层数|初始化方式|early stop at epoch| val_loss | vla_acc|\n",
        "|-|-|-|-|-|\n",
        "|20|默认|\n",
        "|20|xaviier_uniform|\n",
        "|20|he_uniform|\n",
        "|...|\n",
        "\n",
        "He初始化出自论文 《Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification》"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:14.591557Z",
          "start_time": "2025-01-17T02:43:14.582870Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xhmMC0q5hjMT",
        "outputId": "0f4886b6-8b9b-4fb3-ca9a-953e8a6434ae"
      },
      "source": [
        "class NeuralNetwork(nn.Module):\n",
        "    def __init__(self, layers_num=2):\n",
        "        super().__init__()\n",
        "        self.transforms = transforms\n",
        "        self.flatten = nn.Flatten()\n",
        "        # 多加几层\n",
        "        self.linear_relu_stack = nn.Sequential(\n",
        "            nn.Linear(28 * 28, 100),  # in_features=784, out_features=300\n",
        "            nn.ReLU(),\n",
        "            nn.AlphaDropout(p=0.2) # 增加dropout，p=0.2表示以0.2的概率将某些神经元置0，防止过拟合\n",
        "        )\n",
        "        # 加19层\n",
        "        for i in range(1, layers_num):\n",
        "            self.linear_relu_stack.add_module(f\"Linear_{i}\", nn.Linear(100, 100))\n",
        "            self.linear_relu_stack.add_module(f\"relu\", nn.ReLU())\n",
        "            nn.AlphaDropout(p=0.2) # 增加dropout\n",
        "        # 输出层\n",
        "        self.linear_relu_stack.add_module(\"Output Layer\", nn.Linear(100, 10))\n",
        "\n",
        "        # 初始化权重\n",
        "        self.init_weights()\n",
        "\n",
        "    def init_weights(self):\n",
        "        \"\"\"使用 xavier 均匀分布来初始化全连接层的权重 W\"\"\"\n",
        "        for m in self.modules():\n",
        "            if isinstance(m, nn.Linear):\n",
        "                nn.init.xavier_uniform_(m.weight)\n",
        "                nn.init.zeros_(m.bias)\n",
        "\n",
        "    def forward(self, x):\n",
        "        # x.shape [batch size, 1, 28, 28]\n",
        "        x = self.transforms(x)\n",
        "        x = self.flatten(x)\n",
        "        # 展平后 x.shape [batch size, 28 * 28]\n",
        "        logits = self.linear_relu_stack(x)\n",
        "        # logits.shape [batch size, 10]\n",
        "        return logits\n",
        "\n",
        "print(f\"{'layer_name':^40}\\tparamerters num\")\n",
        "for idx, (key, value) in enumerate(NeuralNetwork(20).named_parameters()):\n",
        "    print(\"{:<40}\\t{:^10}\".format(key, np.prod(value.shape)))"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "               layer_name               \tparamerters num\n",
            "linear_relu_stack.0.weight              \t  78400   \n",
            "linear_relu_stack.0.bias                \t   100    \n",
            "linear_relu_stack.Linear_1.weight       \t  10000   \n",
            "linear_relu_stack.Linear_1.bias         \t   100    \n",
            "linear_relu_stack.Linear_2.weight       \t  10000   \n",
            "linear_relu_stack.Linear_2.bias         \t   100    \n",
            "linear_relu_stack.Linear_3.weight       \t  10000   \n",
            "linear_relu_stack.Linear_3.bias         \t   100    \n",
            "linear_relu_stack.Linear_4.weight       \t  10000   \n",
            "linear_relu_stack.Linear_4.bias         \t   100    \n",
            "linear_relu_stack.Linear_5.weight       \t  10000   \n",
            "linear_relu_stack.Linear_5.bias         \t   100    \n",
            "linear_relu_stack.Linear_6.weight       \t  10000   \n",
            "linear_relu_stack.Linear_6.bias         \t   100    \n",
            "linear_relu_stack.Linear_7.weight       \t  10000   \n",
            "linear_relu_stack.Linear_7.bias         \t   100    \n",
            "linear_relu_stack.Linear_8.weight       \t  10000   \n",
            "linear_relu_stack.Linear_8.bias         \t   100    \n",
            "linear_relu_stack.Linear_9.weight       \t  10000   \n",
            "linear_relu_stack.Linear_9.bias         \t   100    \n",
            "linear_relu_stack.Linear_10.weight      \t  10000   \n",
            "linear_relu_stack.Linear_10.bias        \t   100    \n",
            "linear_relu_stack.Linear_11.weight      \t  10000   \n",
            "linear_relu_stack.Linear_11.bias        \t   100    \n",
            "linear_relu_stack.Linear_12.weight      \t  10000   \n",
            "linear_relu_stack.Linear_12.bias        \t   100    \n",
            "linear_relu_stack.Linear_13.weight      \t  10000   \n",
            "linear_relu_stack.Linear_13.bias        \t   100    \n",
            "linear_relu_stack.Linear_14.weight      \t  10000   \n",
            "linear_relu_stack.Linear_14.bias        \t   100    \n",
            "linear_relu_stack.Linear_15.weight      \t  10000   \n",
            "linear_relu_stack.Linear_15.bias        \t   100    \n",
            "linear_relu_stack.Linear_16.weight      \t  10000   \n",
            "linear_relu_stack.Linear_16.bias        \t   100    \n",
            "linear_relu_stack.Linear_17.weight      \t  10000   \n",
            "linear_relu_stack.Linear_17.bias        \t   100    \n",
            "linear_relu_stack.Linear_18.weight      \t  10000   \n",
            "linear_relu_stack.Linear_18.bias        \t   100    \n",
            "linear_relu_stack.Linear_19.weight      \t  10000   \n",
            "linear_relu_stack.Linear_19.bias        \t   100    \n",
            "linear_relu_stack.Output Layer.weight   \t   1000   \n",
            "linear_relu_stack.Output Layer.bias     \t    10    \n"
          ]
        }
      ],
      "execution_count": 4
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LlGpGzC5hjMU"
      },
      "source": [
        "## 训练"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:14.626644Z",
          "start_time": "2025-01-17T02:43:14.592560Z"
        },
        "id": "J6qwFEG4hjMV"
      },
      "source": [
        "from sklearn.metrics import accuracy_score\n",
        "\n",
        "@torch.no_grad()\n",
        "def evaluating(model, dataloader, loss_fct):\n",
        "    loss_list = []\n",
        "    pred_list = []\n",
        "    label_list = []\n",
        "    for datas, labels in dataloader:\n",
        "        datas = datas.to(device)\n",
        "        labels = labels.to(device)\n",
        "        # 前向计算\n",
        "        logits = model(datas)\n",
        "        loss = loss_fct(logits, labels)         # 验证集损失\n",
        "        loss_list.append(loss.item())\n",
        "\n",
        "        preds = logits.argmax(axis=-1)    # 验证集预测\n",
        "        pred_list.extend(preds.cpu().numpy().tolist())\n",
        "        label_list.extend(labels.cpu().numpy().tolist())\n",
        "\n",
        "    acc = accuracy_score(label_list, pred_list)\n",
        "    return np.mean(loss_list), acc\n"
      ],
      "outputs": [],
      "execution_count": 5
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:17.464410Z",
          "start_time": "2025-01-17T02:43:14.626644Z"
        },
        "id": "Bs_LCiVohjMV"
      },
      "source": [
        "from torch.utils.tensorboard import SummaryWriter\n",
        "\n",
        "\n",
        "class TensorBoardCallback:\n",
        "    def __init__(self, log_dir, flush_secs=10):\n",
        "        \"\"\"\n",
        "        Args:\n",
        "            log_dir (str): dir to write log.\n",
        "            flush_secs (int, optional): write to dsk each flush_secs seconds. Defaults to 10.\n",
        "        \"\"\"\n",
        "        self.writer = SummaryWriter(log_dir=log_dir, flush_secs=flush_secs)\n",
        "\n",
        "    def draw_model(self, model, input_shape):\n",
        "        self.writer.add_graph(model, input_to_model=torch.randn(input_shape))\n",
        "\n",
        "    def add_loss_scalars(self, step, loss, val_loss):\n",
        "        self.writer.add_scalars(\n",
        "            main_tag=\"training/loss\",\n",
        "            tag_scalar_dict={\"loss\": loss, \"val_loss\": val_loss},\n",
        "            global_step=step,\n",
        "            )\n",
        "\n",
        "    def add_acc_scalars(self, step, acc, val_acc):\n",
        "        self.writer.add_scalars(\n",
        "            main_tag=\"training/accuracy\",\n",
        "            tag_scalar_dict={\"accuracy\": acc, \"val_accuracy\": val_acc},\n",
        "            global_step=step,\n",
        "        )\n",
        "\n",
        "    def add_lr_scalars(self, step, learning_rate):\n",
        "        self.writer.add_scalars(\n",
        "            main_tag=\"training/learning_rate\",\n",
        "            tag_scalar_dict={\"learning_rate\": learning_rate},\n",
        "            global_step=step,\n",
        "\n",
        "        )\n",
        "\n",
        "    def __call__(self, step, **kwargs):\n",
        "        # add loss\n",
        "        loss = kwargs.pop(\"loss\", None)\n",
        "        val_loss = kwargs.pop(\"val_loss\", None)\n",
        "        if loss is not None and val_loss is not None:\n",
        "            self.add_loss_scalars(step, loss, val_loss)\n",
        "        # add acc\n",
        "        acc = kwargs.pop(\"acc\", None)\n",
        "        val_acc = kwargs.pop(\"val_acc\", None)\n",
        "        if acc is not None and val_acc is not None:\n",
        "            self.add_acc_scalars(step, acc, val_acc)\n",
        "        # add lr\n",
        "        learning_rate = kwargs.pop(\"lr\", None)\n",
        "        if learning_rate is not None:\n",
        "            self.add_lr_scalars(step, learning_rate)\n"
      ],
      "outputs": [],
      "execution_count": 6
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:17.468381Z",
          "start_time": "2025-01-17T02:43:17.464410Z"
        },
        "id": "3MzCrGEuhjMW"
      },
      "source": [
        "class SaveCheckpointsCallback:\n",
        "    def __init__(self, save_dir, save_step=5000, save_best_only=True):\n",
        "        \"\"\"\n",
        "        Save checkpoints each save_epoch epoch.\n",
        "        We save checkpoint by epoch in this implementation.\n",
        "        Usually, training scripts with pytorch evaluating model and save checkpoint by step.\n",
        "\n",
        "        Args:\n",
        "            save_dir (str): dir to save checkpoint\n",
        "            save_epoch (int, optional): the frequency to save checkpoint. Defaults to 1.\n",
        "            save_best_only (bool, optional): If True, only save the best model or save each model at every epoch.\n",
        "        \"\"\"\n",
        "        self.save_dir = save_dir\n",
        "        self.save_step = save_step\n",
        "        self.save_best_only = save_best_only\n",
        "        self.best_metrics = -1\n",
        "\n",
        "        # mkdir\n",
        "        if not os.path.exists(self.save_dir):\n",
        "            os.mkdir(self.save_dir)\n",
        "\n",
        "    def __call__(self, step, state_dict, metric=None):\n",
        "        if step % self.save_step > 0:\n",
        "            return\n",
        "\n",
        "        if self.save_best_only:\n",
        "            assert metric is not None\n",
        "            if metric >= self.best_metrics:\n",
        "                # save checkpoints\n",
        "                torch.save(state_dict, os.path.join(self.save_dir, \"best.ckpt\"))\n",
        "                # update best metrics\n",
        "                self.best_metrics = metric\n",
        "        else:\n",
        "            torch.save(state_dict, os.path.join(self.save_dir, f\"{step}.ckpt\"))\n",
        "\n"
      ],
      "outputs": [],
      "execution_count": 7
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T02:43:17.472127Z",
          "start_time": "2025-01-17T02:43:17.468381Z"
        },
        "id": "6HgTK_iBhjMW"
      },
      "source": [
        "class EarlyStopCallback:\n",
        "    def __init__(self, patience=5, min_delta=0.01):\n",
        "        \"\"\"\n",
        "\n",
        "        Args:\n",
        "            patience (int, optional): Number of epochs with no improvement after which training will be stopped.. Defaults to 5.\n",
        "            min_delta (float, optional): Minimum change in the monitored quantity to qualify as an improvement, i.e. an absolute\n",
        "                change of less than min_delta, will count as no improvement. Defaults to 0.01.\n",
        "        \"\"\"\n",
        "        self.patience = patience\n",
        "        self.min_delta = min_delta\n",
        "        self.best_metric = -1\n",
        "        self.counter = 0\n",
        "\n",
        "    def __call__(self, metric):\n",
        "        if metric >= self.best_metric + self.min_delta:\n",
        "            # update best metric\n",
        "            self.best_metric = metric\n",
        "            # reset counter\n",
        "            self.counter = 0\n",
        "        else:\n",
        "            self.counter += 1\n",
        "\n",
        "    @property\n",
        "    def early_stop(self):\n",
        "        return self.counter >= self.patience\n"
      ],
      "outputs": [],
      "execution_count": 8
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T03:03:39.075593Z",
          "start_time": "2025-01-17T02:43:17.473138Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 67,
          "referenced_widgets": [
            "754aec9e3b8f4599af03b992b8f4a647",
            "1acb17a0acd5483c8dfbcc522b9eb610",
            "078907447bb14f2e99b6eabd92328421",
            "58d4ff0313c64a86872b5ebde5506603",
            "d4b7a7c89c174a9a8fc82aa2a13de84a",
            "c80769781adc48538f482b9a739bcf5f",
            "8bf51169fcc94d67adea09f826735702",
            "a14135c169cc447c9b55ab6f3001c577",
            "6d159ae46c8a484db9a0bb2f04654b07",
            "2d993a4cc36a44ca95f6c6e5ce83c6a5",
            "5c46479c2fbd4faa98d099c738227cfa"
          ]
        },
        "id": "gZFeeCbshjMX",
        "outputId": "c9143756-74f9-4b5b-83aa-e3ac74adf1aa"
      },
      "source": [
        "# 训练\n",
        "def training(\n",
        "    model,\n",
        "    train_loader,\n",
        "    val_loader,\n",
        "    epoch,\n",
        "    loss_fct,\n",
        "    optimizer,\n",
        "    tensorboard_callback=None,\n",
        "    save_ckpt_callback=None,\n",
        "    early_stop_callback=None,\n",
        "    eval_step=500,\n",
        "    ):\n",
        "    record_dict = {\n",
        "        \"train\": [],\n",
        "        \"val\": []\n",
        "    }\n",
        "\n",
        "    global_step = 0\n",
        "    model.train()\n",
        "    with tqdm(total=epoch * len(train_loader)) as pbar:\n",
        "        for epoch_id in range(epoch):\n",
        "            # training\n",
        "            for datas, labels in train_loader:\n",
        "                datas = datas.to(device)\n",
        "                labels = labels.to(device)\n",
        "                # 梯度清空\n",
        "                optimizer.zero_grad()\n",
        "                # 模型前向计算\n",
        "                logits = model(datas)\n",
        "                # 计算损失\n",
        "                loss = loss_fct(logits, labels)\n",
        "                # 梯度回传\n",
        "                loss.backward()\n",
        "                # 调整优化器，包括学习率的变动等\n",
        "                optimizer.step()\n",
        "                preds = logits.argmax(axis=-1)\n",
        "\n",
        "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())\n",
        "                loss = loss.cpu().item()\n",
        "                # record\n",
        "\n",
        "                record_dict[\"train\"].append({\n",
        "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
        "                })\n",
        "\n",
        "                # evaluating\n",
        "                if global_step % eval_step == 0:\n",
        "                    model.eval()\n",
        "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
        "                    record_dict[\"val\"].append({\n",
        "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
        "                    })\n",
        "                    model.train()\n",
        "\n",
        "                    # 1. 使用 tensorboard 可视化\n",
        "                    if tensorboard_callback is not None:\n",
        "                        tensorboard_callback(\n",
        "                            global_step,\n",
        "                            loss=loss, val_loss=val_loss,\n",
        "                            acc=acc, val_acc=val_acc,\n",
        "                            lr=optimizer.param_groups[0][\"lr\"],\n",
        "                            )\n",
        "\n",
        "                    # 2. 保存模型权重 save model checkpoint\n",
        "                    if save_ckpt_callback is not None:\n",
        "                        save_ckpt_callback(global_step, model.state_dict(), metric=val_acc)\n",
        "\n",
        "                    # 3. 早停 Early Stop\n",
        "                    if early_stop_callback is not None:\n",
        "                        early_stop_callback(val_acc)\n",
        "                        if early_stop_callback.early_stop:\n",
        "                            print(f\"Early stop at epoch {epoch_id} / global_step {global_step}\")\n",
        "                            return record_dict\n",
        "\n",
        "                # udate step\n",
        "                global_step += 1\n",
        "                pbar.update(1)\n",
        "                pbar.set_postfix({\"epoch\": epoch_id})\n",
        "\n",
        "    return record_dict\n",
        "\n",
        "\n",
        "epoch = 100\n",
        "\n",
        "model = NeuralNetwork(layers_num=10)\n",
        "\n",
        "# 1. 定义损失函数 采用交叉熵损失\n",
        "loss_fct = nn.CrossEntropyLoss()\n",
        "# 2. 定义优化器 采用SGD\n",
        "# Optimizers specified in the torch.optim package\n",
        "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)\n",
        "\n",
        "# 1. tensorboard 可视化\n",
        "tensorboard_callback = TensorBoardCallback(\"runs/dropout\")\n",
        "tensorboard_callback.draw_model(model, [1, 28, 28])\n",
        "# 2. save best\n",
        "save_ckpt_callback = SaveCheckpointsCallback(\".\", save_best_only=True)\n",
        "# 3. early stop\n",
        "early_stop_callback = EarlyStopCallback(patience=10, min_delta=0.001)\n",
        "\n",
        "model = model.to(device)\n",
        "record = training(\n",
        "    model,\n",
        "    train_loader,\n",
        "    val_loader,\n",
        "    epoch,\n",
        "    loss_fct,\n",
        "    optimizer,\n",
        "    tensorboard_callback=tensorboard_callback,\n",
        "    save_ckpt_callback=save_ckpt_callback,\n",
        "    early_stop_callback=early_stop_callback,\n",
        "    eval_step=len(train_loader)\n",
        "    )"
      ],
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "  0%|          | 0/375000 [00:00<?, ?it/s]"
            ],
            "application/vnd.jupyter.widget-view+json": {
              "version_major": 2,
              "version_minor": 0,
              "model_id": "754aec9e3b8f4599af03b992b8f4a647"
            }
          },
          "metadata": {}
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Early stop at epoch 55 / global_step 206250\n"
          ]
        }
      ],
      "execution_count": 11
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T03:03:39.241147Z",
          "start_time": "2025-01-17T03:03:39.075660Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 465
        },
        "id": "Ywysng4uhjMX",
        "outputId": "decae11a-af3a-4024-e800-a61ef3cf6cfb"
      },
      "source": [
        "#画线要注意的是损失是不一定在零到1之间的\n",
        "def plot_learning_curves(record_dict, sample_step=500):\n",
        "    # build DataFrame\n",
        "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
        "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
        "\n",
        "    # plot\n",
        "    fig_num = len(train_df.columns)\n",
        "    fig, axs = plt.subplots(1, fig_num, figsize=(6 * fig_num, 5))\n",
        "    for idx, item in enumerate(train_df.columns):\n",
        "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
        "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
        "        axs[idx].grid()\n",
        "        axs[idx].legend()\n",
        "        axs[idx].set_xlabel(\"step\")\n",
        "\n",
        "    plt.show()\n",
        "\n",
        "plot_learning_curves(record, sample_step=10000)  #横坐标是 steps"
      ],
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "<Figure size 1200x500 with 2 Axes>"
            ],
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAA9UAAAHACAYAAACszkseAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAv+lJREFUeJzs3Xd4W+X5//G3lrcdZ9nOcOLsvRMy2CUDQlNGoZQVdltK2kI602/LKL9CB6sDCoVCQpktBUpJCDGBJEAWSXDI3rGz7ExbnrIsnd8fx5LteNsatvV5XZcuW/I5R4+PlUj3ue/nfiyGYRiIiIiIiIiISLNZwz0AERERERERkfZKQbWIiIiIiIhICymoFhEREREREWkhBdUiIiIiIiIiLaSgWkRERERERKSFFFSLiIiIiIiItJCCahEREREREZEWUlAtIiIiIiIi0kL2cA+gKbxeL0ePHiUxMRGLxRLu4YiISIQzDIPCwkJ69uyJ1arr04Gg93oREWlrmvp+3y6C6qNHj5Kenh7uYYiIiNRw6NAhevfuHe5hdAh6rxcRkbaqsff7dhFUJyYmAuYvk5SU1Kpjud1uli1bxsyZM3E4HIEYnjRC5zz0dM5DT+c8PMJ13p1OJ+np6f73J2k9vde3bzrn4aHzHno656EXznPe1Pf7dhFU+8rAkpKSAvJGGxcXR1JSkv4hhIjOeejpnIeeznl4hPu8q0w5cPRe377pnIeHznvo6ZyHXls4542932simIiIiIiIiEgLKagWERERERERaSEF1SIiIiIiIiIt1C7mVIuItCeGYVBRUYHH4wn3UDo8t9uN3W6nrKws4OfbZrNht9s1b1pEREQapKBaRCSA3G43R48epaSkJNxDiQiGYZCWlsahQ4eCEvzGxcXRo0cPoqKiAn5sERER6RgUVIuIBFBOTg52u52ePXsSFRWlLGeQeb1eioqKSEhIwGoN3IwmwzAoLy/nxIkTHDhwgEGDBgX0+CIiItJxKKgWEQkQu92O1+ulZ8+exMXFhXs4EcHr9VJeXk5MTEzAg97Y2FgcDgfZ2dn+5xARERE5my67i4gEmDKaHYf+liIiItIYfVoQERERERERaSEF1SIiIiIiIiItpKBaREQCKiMjg6eeeiogx1qxYgUWi4X8/PyAHE+aZtWqVcyZM4eePXtisVh49913G91nxYoVjB8/nujoaAYOHMjChQuDPk4REZG2QEG1iIhw0UUXce+99wbkWF988QXf+c53AnIsCY/i4mLGjBnD008/3aTtDxw4wOWXX87FF19MVlYW9957L3feeScffvhhkEcqIiISfur+LSIijTIMA4/Hg93e+NtG9+7dQzAiCabLLruMyy67rMnbP/vss/Tr14/HH38cgGHDhvHZZ5/x5JNPMmvWrGANU0REpE2IqKD6WEEpdy3aQH6Bjdmzwz0aEYkEhmFQ6vaE5bljHbYmrZN96623snLlSlauXMmf/vQnAF566SVuu+02lixZwq9+9Su2bNnCsmXLSE9PZ/78+axdu5bi4mKGDRvGo48+yvTp0/3Hy8jI4N577/Vnvi0WC88//zyLFy/mww8/pFevXjz++ON84xvfaNHv9Z///If777+fvXv30qNHD+68805++ctf+n/+zDPP8OSTT3Lo0CE6derE+eefz1tvvQXAW2+9xUMPPcTevXuJi4tj3Lhx/Pe//yU+Pr5FYxHTmjVrarwGAGbNmtVg9YPL5cLlcvnvO51OANxuN263u1Xj8e3f2uO0Vc+tOsCBU8X8Zs5wouxto+iwo5/ztkrnPfR0zkMvnOe8qc8ZUUG1zWph61EnFsDrNcI9HBGJAKVuD8PvD08J7PbfzCIuqvH/5v/0pz+xe/duRo4cyW9+8xsAtm3bBsAvfvELHnvsMfr370/nzp05dOgQs2fP5re//S3R0dG8/PLLzJkzh127dtGnT596n+Ohhx7iD3/4A3/84x/5y1/+wo033kh2djZdunRp1u+0ceNGvvWtb/Hggw9y3XXX8dlnnzFv3jx69uzJ7bffzoYNG/jhD3/IP//5T6ZNm8bp06f59NNPATh27BjXX389f/jDH7jqqqsoLCzk008/xTD0ftBaubm5pKam1ngsNTUVp9NJaWkpsbGxtfZ59NFHeeihh2o9vmzZsoCt856ZmRmQ47QlxW54fIMNAwuxzkNM6t62Xr8d8Zy3BzrvoadzHnrhOOclJSVN2i6iguqkGAcABhaKyz1ER4d5QCIibUCnTp2IiooiLi6OtLQ0AHbu3AnAb37zG2bMmOHftkuXLowZM8Z//+GHH+add97hvffeY968efU+x6233sr1118PwCOPPMKf//xn1q9fz6WXXtqssT7xxBNccskl/PrXvwZg4MCBZGVl8fjjj3P77beTk5NDfHw8X//610lMTKRv376MGzcOMIPqiooKrr76avr27QvAqFGjmvX8EjgLFixg/vz5/vtOp5P09HRmzpxJUlJSq47tdrvJzMxkxowZOByO1g61TVm8JRdjw1cAfFXWmQdmTwnziEwd+Zy3ZTrvoadzHnrhPOe+KqrGRFRQHeOw4bBZcHsMCsvcdEmsfeVcRCSQYh02tv8mPHNKYx22Vh9j4sSJNe4XFRXx4IMPsnjxYn+QWlpaSk5OToPHGT16tP/7+Ph4kpKSOH78eLPHs2PHDq644ooaj02ZMoVnn30Wj8fDjBkz6Nu3L/379+fSSy/l0ksv5aqrriIuLo4xY8ZwySWXMGrUKGbNmsXMmTO55ppr6Ny5c7PHITWlpaWRl5dX47G8vDySkpLqzFIDREdHE13H1W2HwxGwD02BPFZb8ene0/7vvzrsZFtuMWPTk8M3oLN0xHPeHui8h57OeeiF45w39fnaxkScEEqMMa8jFJZVhHkkIhIJLBYLcVH2sNyaMp+6MWfPNf7JT37CO++8wyOPPMKnn35KVlYWo0aNory8vMHjnP2mZLFY8Hq9rR7f2RITE9m0aROvv/46PXr04P7772fMmDHk5+djs9nIzMzkgw8+YPjw4fzlL39hyJAhHDhwIODjiDRTp05l+fLlNR7LzMxk6tSpYRpRx+T1GqzcfQKA/t3Mf5uLVh8M44hERASaGVQ/+uijTJo0icTERFJSUrjyyivZtWtXg/ssXLgQi8VS4xYTE9OqQbdGYrT5wa7QpaBaRMQnKioKj6fxhmqff/45t956K1dddRWjRo0iLS2NgwcPBn+AlYYNG8bnn39e47G1a9cyePBgbDYzM2+325k+fTp/+MMf+Oqrrzh48CAff/wxYAbz5557Lg899BBffvklUVFRvPPOOyEbf3tRVFREVlYWWVlZgLlkVlZWlr8iYcGCBcydO9e//fe+9z3279/Pz372M3bu3MkzzzzDv/71L+67775wDL/D2n7MyckiF3FRNv5wjVn98f5XRzlR6GpkTxERCaZmlX+vXLmSe+65h0mTJlFRUcEvf/lLZs6cyfbt2xvsnJqUlFQj+A5E9qSlkmKVqRYROVtGRgbr1q3j4MGDJCQk1JtFHjRoEG+//TZz5szBYrHw61//OigZ5/r8+Mc/ZtKkSTz88MNcd911fP7557zwwgv89a9/BeD9999n//79XHDBBXTu3JklS5bg9XoZMmQI69atY/ny5cycOZOUlBTWrVvHiRMnGDZsWMjG315s2LCBiy++2H/fN/f5lltuYeHChRw7dqxGyX+/fv1YvHgx9913H3/605/o3bs3L7zwgpbTCjBflnragG5MzOjC2PRksg7l8/r6HH54yaAwj05EJHI1K6heunRpjfsLFy4kJSWFjRs3csEFF9S7n8Vi8Te/CbfEaPNXdiqoFhHx+8lPfsItt9zC8OHDKS0t5aWXXqpzuyeeeILbb7+dadOm0a1bN37+8583uYlHIIwfP55//etf3H///Tz88MP06NGDBQsWcOuttwKQnJzM22+/zYMPPkhZWRmDBg3i9ddfZ8SIEezYsYNVq1bx1FNP4XQ66du3L48//niz1mOOFBdddFGDXdEXLlxY5z5ffvllEEclK3aZfQguGmKuBX/rtAzufTOLV9dlc/dFA3DYIm5Wn4hIm9CqRmUFBQUAjS6JUlRURN++ffF6vYwfP55HHnmEESNG1Lt90Nau9LjpZzlGnuUkBcWDtb5ciGg9v9DTOQ8937k2DAOv1xvS7G0gDBw4sFZZta+8t/rv0qdPHz766KMa29199901ttu/f3+N+76y8urHOX36dK3H6nLBBRfU2v+qq67iqquuAszzXVhY6D/v06ZN85d6V+fLVi9ZsqTOn9XH6/ViGAZut9tfXg76tyWhV1DqZlNOPgAXDjaD6tmjevD/Fu8gz+li6dZc5ozpGcYRiohErhYH1V6vl3vvvZdzzz2XkSNH1rvdkCFDePHFFxk9ejQFBQU89thjTJs2jW3bttG7d+869wnW2pWx5Sf57ZH5uKIc/Hjbi3TL397iY0nzaT2/0NM5Dy273U5ZWRlFRUWNNu6SwCosLAzKccvLyyktLWXVqlVUVFRVODV13UqRQPl870k8XoMB3eNJ72J+FoqyW7lhch/+vHwPi1YfVFAtIhImLQ6q77nnHrZu3cpnn33W4HZTp06t0f1z2rRpDBs2jOeee46HH364zn2CtnZl0XHYNh8HFaT2ymD2bM2jCwWt5xd6Oueh53a7+eSTT4iJiSEhISGsDRnbk7vvvptXX321zp/deOON/O1vf2twf1+mOjExMSj9OsrKyoiNjeWCCy6o8TcNZcm7CFQv/U6p8fiNk/vwzCd72ZB9hq1HChjZq1M4hiciEtFaFFTPmzeP999/n1WrVtWbba6Pw+Fg3Lhx7N27t95tgrZ2ZYx5ZddqMSh1uxVshJjW8ws9nfPQs1gsWK1WrFbNbWyKhx9+mJ/+9Kd1/iwpKanR8+gr3fad90CzWq1YLJZa/5b070pCyTCqltLylX77pCbFcNmoHvxv81EWrT7IH68dE44hiohEtGYF1YZh8IMf/IB33nmHFStW0K9fv2Y/ocfjYcuWLcyePbvZ+7aaLcr/bWlpaeifX0REakhJSSElJaXxDUUi2M7cQvKcLmIdNs7pV7uPza3T+vK/zUf57+ajLJg9jC7xUXUcRUREgqVZl/XvueceXnnlFV577TUSExPJzc0lNze3RoA6d+5cFixY4L//m9/8hmXLlrF//342bdrETTfdRHZ2NnfeeWfgfoumslVlv8vKykL//CIiIiLNtGKXmaWeOqArMQ5brZ+P79OZkb2SKK/w8sYXObV+LiIiwdWsoPpvf/sbBQUFXHTRRfTo0cN/e/PNN/3b5OTkcOzYMf/9M2fOcNdddzFs2DBmz56N0+lk9erVDB8+PHC/RVNZbRiYc+7KytRkRkRERNo+33zqs0u/fSwWC7dMzQDglTXZVHja1+oDIiLtXbPLvxuzYsWKGveffPJJnnzyyWYNKmgsFgyrA4u3HFeZq/HtRURERMKosMzNxuwzQNX61HWZM6Ynj36wk6MFZXy0I49LR/YI1RBFRCJexHXSMSrnVbvKVf4tIiIibdvne09R4TXo1y2evl3j690uxmHj25PSAVi4+mCIRiciIhCBQbWvWZnbpaBaRERE2raVuxsu/a7upil9sVktrN1/mp25WvZNRCRUIjao9rjLNedIRCRAMjIyeOqpp5q0rcVi4d133w3qeEQ6AsMwWFnZpOzCBkq/fXomxzJzeCoAi1ZnB3VsIiJSJeKCaovdDKodVFDkqgjzaERERETqtud4EUcLyoi2W5nav2uT9rllWgYA7355hIISdxBHJyIiPhEbVEfhxlmqoFpERETaJl/X7yn9615Kqy6T+3VhaFoipW4P/9pwKJjDExGRShEXVPvKvx2WCpxluoIrIkFmGFBeHJ5bE1ZsAPj73/9Oz5498XprTom54ooruP3229m3bx9XXHEFqampJCQkMGnSJD766KOAnaItW7bwta99jdjYWLp27cp3vvMdioqK/D9fsWIF55xzDvHx8SQnJ3PuueeSnW2Wtm7evJk5c+bQqVMnkpKSmDBhAhs2bAjY2ETCaeXuytLvJsyn9rFYLNxama1+ee1BPN6m/T8gItJWHTpTgqeN/1fWrCW1OgLDFoUFs/y7sEyZahEJMncJPNIzPM/9y6MQVX+3YJ9rr72WH/zgB3zyySdccsklAJw+fZqlS5eyZMkSioqKmD17Nr/97W+Jjo7m5ZdfZs6cOezatYs+ffq0aojFxcXMmjWLqVOn8sUXX3D8+HHuvPNO5s2bx8KFC6moqODKK6/krrvu4vXXX6e8vJz169djsVgAuPnmmxkxYgTPPfccDoeDrKwsHA5Hq8Yk0hYUuyr44kDjS2nV5YqxvXj0g50cOl3KJzuPM71ynnUwLVqTzZNf2PjlpuVYsAT9+ZrKZrXws0uHcOPkvuEeSkQoKHFz+6IvOG9gN+6bMTjcw5EOILegjOuf/4IuNisXXVJBlzb6Hh9xQbUvUx1NBYXKVIuI0LlzZy677DJee+01f1D91ltv0a1bNy6++GKsVitjxozxb//www/zzjvv8N577zFv3rxWPfdrr71GWVkZL7/8MvHx5gWAv/71r8yZM4ff//73OBwOCgoK+PrXv86AAQMAGDZsmH//nJwc7rnnHoYOHYrVamXQoEGtGo9IW7F63ynKPV76dImjX7fGL45VFxtlLq/13Kr9LFpzMOhB9X+zjvD/luwCLFDhCepztcTjy3bzzfG9m1xCLy23eMsxNmafYeuRAu6+aIDOubRKsauCOxZ9QV6hC0usBWi76eoIDKrNqxsOKnAqUy0iweaIMzPG4XruJrrxxhu56667eOaZZ4iOjubVV1/l29/+NlarlaKiIh588EEWL17MsWPHqKiooLS0lJycnFYPcceOHYwZM8YfUAOce+65eL1edu3axQUXXMCtt97KrFmzmDFjBtOnT+db3/oWPXr0AOC+++7jhz/8If/5z3+YPn061157rT/4FmnPfPOpLxzc3V+Z0Rw3TenL85/u59M9J9l7vIiBKQmBHiIAGw6e5qf//gqAC9O8/PrbF2C3t42PlwZww/NrOVZQxvtfHeOaCb3DPaQOz/e6dVV4Wbv/FBcNSQnziKS98ngNfvTGl2w76qRrfBTfGVxCYkzbzFJDRAbV0YCv/FuZahEJMoulSSXY4TZnzhwMw2Dx4sVMmjSJTz/9lCeffBKAn/zkJ2RmZvLYY48xcOBAYmNjueaaaygvLw/J2F566SV++MMfsnTpUt58801+9atfkZmZyZQpU3jggQeYM2cOq1atYunSpTzwwAO88cYbXHXVVSEZm0gwGIbhn0/d3NJvn/QucVwyLJXM7Xm8vOYgv7liZCCHCEDOqRK+88+NlHu8TB/ancuTj9G3a1ybmoJx05S+/PHDXSxafZBvju/VogsU0jTlFV5W7zvlv79i1wkF1dJijyzZwUc7jhNlt/K3G8dybMvqcA+pQRHYqMz8jz7KojnVIiI+MTExXH311bz66qu8/vrrDBkyhPHjxwPw+eefc+utt3LVVVcxatQo0tLSOHjwYECed9iwYWzevJni4mL/Y59//jlWq5UhQ4b4Hxs3bhwLFixg9erVjBw5ktdee83/s4EDB3LvvfeybNkyrr76al566aWAjE0kXPadKObwmVKibFamDmjaUlp18TUs+8/GwwFPJBSUurlt4XpOF5czomcSj187CmsbjFe/PSmdKLuVLUcK2JSTH+7hdGgbs8/UWK7Wd2FIpLn+uTabf3x2AIDHrx3DuPTk8A6oCSIwqK5ap9pZqky1iIjPjTfeyOLFi3nxxRe58cYb/Y8PGjSIt99+m6ysLDZv3swNN9xQq1N4a54zJiaGW265ha1bt/LJJ5/wgx/8gJtvvpnU1FQOHDjAggULWLNmDdnZ2Sxbtow9e/YwbNgwSktL+cEPfsBnn31GdnY2n3/+OV988UWNOdci7ZGvhPacfl2Ii2p5UeG0AV0ZlJJAcbmHtzYeDtTwcHu8fP/Vjew7UUxaUgz/uGVSq8YZTF0Topkz2mwWuWj1wfAOpoNbsdt83c4YnordauHAyWKyTxU3spdITSt3n+DB97YB8JOZg5kzJkzNXpspYoPqaNzKVIuIVPO1r32NLl26sGvXLm644Qb/40888QSdO3dm2rRpzJkzh1mzZvmz2K0VFxfHhx9+yOnTp5k0aRLXXHMNl1xyCX/961/9P9+5cyff/OY3GTx4MN/5zne45557+O53v4vNZuPUqVN873vfY+jQoXzrW9/isssu46GHHgrI2ETCpbWl3z4Wi4W5vuW11mTjDcDyWoZh8Ot3t/L53lPERdl44ZaJpHWKafVxg8mXsV+y5RjHnWXhHUwHtnKX+br9+ugeTOjb2XxM2Wpphl25hcx7dRMer8HV43txz8UDwz2kJmublxWDqVqmutClTLWIiI/VauXo0dpN1TIyMvj4449rPHbPPffUuN+ccnDjrPWzR40aVev4Pqmpqbzzzjt1/iwqKorXXnsNp9NJUlISVmvkXSeWjqe03MO6A6eB1gfVAFeP68Uflu7kwMliVu45wcWtnOP6/Kf7eeOLQ1gs8Odvj2Nkr06tHmOwjerdifF9ktmUk8+r63K01FMQ5BaUsTO3EIsFzh/UnSP5paw7cJoVu04wd2pGuIcn7cCJQhe3L/yCQlcF5/TrwqNXj2pXPRAi7hOIUT2oVqZaRERE2pA1+09SXuGlV3IsA7q3vmN3fLSdayekA60vf166NZdHP9gJwK8uHx6S9a8D5ZbKbPVr63MorwjM9BWpsrKy9HtM72S6xEdx0WDz4s3qfScpc7e9ZdakbSlze7jr5Q0cyS8lo2scz900gWh7+1qOLeKCal+mOsqiOdUiIoH26quvkpCQUOdtxIgR4R6eSJvnK6G9cEjLltKqy9ypfbFYzG7MB062bI7rlsMF3PvmlxgG3DSlD7efmxGQsYXKZSN70D0xmhOFLj7Yeizcw+lwzp6yMKxHIimJ0ZS5vXxx8HQ4hyZtnNdr8ON/bSbrUD6dYh28eOskOsdHhXtYzRaBQXXVOtXKVIuIBNY3vvENsrKy6rwtWbIk3MMTafNW+IKTwa0v/fbJ6BbvP97Law42e/+j+aXcsegLytxezh/UjQfnjGhXZZkAUXYrN03uC8BCNSwLqAqPl0/3nATMddXBnM/v+37FLs2rlvo9kbmbxVuO4bBZeO7mCfQPQIVOOERgUG2uUx1FBU4F1SIiAZWYmMjAgQPrvPXt2zfcwxNp08xuySU4bBamDewW0GP7yp/f2nCYYlfTP/8UuSq4Y9EGjhe6GJyawNM3jsdua58fH6+fnI7DZuHLnHy+Opwf7uF0GJty8iksq6BznIPRvZP9j/vWqPZ1sxc521sbD/PXT/YC8OjVo5nSv+VLCIZb+/xfsTV861TjxhngNRtFRKB2Iy5pv/S3lFBaWRl8TOzbhYTowPaSvWBQd/p1i6fQVcHbm5q2vJbHa/DD179kxzEn3RKi+Mctk0iKcQR0XKGUkhjD5aN6AMpWB5JvPvUFg7tjq7ZY+XmDumGzWth3ophDp0vCNTxpo9buP8WCt78CYN7FA7lmQu8wj6h1IjCo9jUq81Be4cVVoeYJIhIYHo/5/0lJiT48dBS+v6XD0X4DCWk/VgRoKa26WK0W5k41q0UWrclu0gWj/7d4Ox/vPE603crzcyeS3iUu4OMKNV/G/v3NxzhZ5ArvYDoIX3n3hWdNWegU62B8n2RAS2tJTftPFPHdf27E7TG4fHQP5neAjvyRt6SWvapRGUBhWQXRCe2ru5yItE2GYZCUlMTx4+ZV+7i4uHY377C98Xq9lJeXU1ZWFtAltQzDoKSkhOPHj5OcnIzNpvcJCa4yt4c1+04BVWWzgXbNhN489uEu9h4v4vO9pzhvUP0l5i+vOchLnx8E4IlvjWVcn85BGVOojevTmTG9O7H5cAFvrM9h3tcGhXtI7drxwjK2HXUCZqb6bBcO7s4XB8+wYtcJbpqiKUACZ4rLuWPRBgpK3YxNT+bxa8dgtbb/z0qRF1RbzaA61loVVHdLiA7niESkA0lJScFms/kDawkuwzAoLS0lNjY2KBcwkpOTSUtLC/hxRc627sBpXBVe0pJiGJwanEY9iTEOvjmhNy+vyWbh6oP1BtUrdh3nwfe2AfDTWUO4fHSPoIwnXG6ZlsH8f23mlbU5fPfCATja6RzxtmDVbrNB2ejener8PH3RkBQeW7ab1fvMpeKi7DrXkay8wst3X9nIgZPF9EqO5fm5E4lxdIyL1hEXVBuVc6pjbeYahVpWS0QCyWKx0KNHD1JSUnC79f9LsLndblatWsUFF1wQ8BJth8OhDLWEjK+Z00UBXEqrLnOnZvDymmyW78zj0OmSWiXdO3OdzHvtS7yGmdn+/kUDgjaWcLl8dA8eWbKDXGcZy7bldbiLBqHke92eXfrtM7xHEt0SojlZ5GLDwdMBb8An7YdhGCx4ewvrD5wmMdrOS7dNontix0lsRlxQjd3848VazbmPWlZLRILBZrMpIAsBm81GRUUFMTExmvcs7ZpvfepgzKeubmBKAucP6sane07yz7XZ/HL2MP/PjheWccfCDRS5KpjcrwuPXDWqQ05hibbbuP6cPvzl470sWn1QQXULVV9Kq77XrdVq4YLB3Xh70xFW7D6hoDrQKsrNJszt4N/p05/s5T+bDmOzWvjrjeMZnJoY7iEFVOQF1b5Mtb/8W5kkERERCZ+cUyXsP1mM3Rr4pbTqcsvUDD7dc5I3vzjEfdMHExtlo7Tcw10vb+RIfin9usXz3M0TOnSp7o2T+/K3FftYf/A02486Gd4zKdxDanc2H86noNRNp1gHY6otpXW2i4ak8PamI6zcdaLGRZwOweuFsnwoPgklp6D0NFhsEBUHjjhwxFZ+jQNHTOU+nspbRdXN8EJ8N4jp1PDzlZ6B7NVw8DM4+CnkbjX36zGm5i25b81A2+uFkpNQeAwK86Ao1zxWab45/rKCqu/Li6HLAOg5DnqNg57jIa5L085HeQnkZ8OZ7MqvB+FMNmeO5zDkpINf2VMZNXock63RcLo/dEoHmx08Feb2p/ZW3U7ugYJDYI/FFtOJcwpc2N573xxLTDJEJ5jP53JW/g5O8/dwVX4dfwucd2+z/pytEYFBta9RmZmp1rJaIiIiEk6+JYnG9+0ckiWrLh6aQnqXWA6dLuXdrCNcNzGdH/87i82H8kmOc/DirZNIjosK+jjCKa1TDLNGprH4q2MsWn2Q318zOtxDand81RUXD0jAfnIHnD4Ap/ebwVFiD+h3IfQcx/kDu2G1wK68Qo7ml9IzObb2wTwVcHofeMrBFm1WltpjKr9Gm4811ozS6zGf+8RuOLnL/Hp6H8R2gdThkDIcUkeYAaOtWghkGOA8CnlbIfcrM1A9vgM8LrDaq91sYLVjw8LXTh3Fvmu+GUQb3sCd1OhOkJwOnXqbAWdyOsSnmOPyBdGc1bm/+ATs/ci8+cR0gtSR4C6FwlwoPm4G7011YifsWlx1P7kv9BoPaaPMAL30jHkry6/6vuSUOZY6dAZm+Ir3tn8A2yu/t9ohIQ2K8sBbf0xmBXoAbPmy6b+D82jTtw2AiA2qo6t1/xYREREJlxUhKv32sVktzJ2SwW+X7GDR6oPknC5hyZZcHDYLz900gX7d4kMyjnC7dVoGi786xrtZR/jFZUPpHB+gCwmGAXnbzCxbmbNmJs3lNL/GdILuQ6H7EPNrYlrbKuH1ZTaLT0DJaTN4LDllfl9ifj9z+1ZuiD5C2t4zsLeugzwMUYl0zjiX/+vah3+f6s/KXXlcP7E3nNwNx7Lg6JdwNAtyt0BFacNjssdAVDw44s2vUXHmV3ssOI+Y2c2Ksrr3rR4g2qKh+2DzvBflmYFq6ekmnxorUKtwOboTxHeF2M5mkO0uBXeJ+bW8xPz+7GC4esCOBcoLwVUAeQVmgF+fboMh4zzz1vscKDpunstjm83b8e1mpjb787N2tEBCivlaS0irzPh2MrO+MZ0gtvKrPRpO7IIjm8y/z+l95sWK/GzY9k7jJyi6E3TuC5374oztzTNfutnvSuSCHh5uGOTFeqby4suZA+bfy3nY3M8eC10HQNeB5q3bIDOY97ioKDrF1i8+ZdSgPtjKC81/T64i8zUQ0wmikyp/l05V95PTGx9rAEVuUI0ZTDsVVIuIiEiYlLk9rK5cSqu+Zk/B8K2J6TyRuZuduYXszC0E4HdXj2Zy/64hG0O4TezbmeE9kth+zMmbGw7xvQtb0ZSt5DTs+xj2Lod9y81grTmqB9mxXQDDDM59X33fx3Qys5hJvaBTOp6Ys14zFS4zY3xqT2UJ7V4zKDKMqqApJrna953M4MR5xMzsOY9U3o41mDkEGAnguw4Q08nMAHfpD8l9zOc/8KkZ/Oxeyh3AHdFQ9OEjkOmuO4B2xJslvRWuylsZNQLRirLKx07VPyhbtBmMdRtsnsuuA6H4BEbeNjy527Gd3IHFXWIG8blb/LsZFhveroPxpIzA030EnpThGFGJ4K3A4vWA4SvV9uBxu9iwZQ/jzpuBLSkFI7aLP76ol2GYmW+L1QyiLXVk3cuLsRYewVpwCKvzMFbnIazOI1iKcvF2GUhF+jQq0qdhJKTW3K9LKnQZRdKE282lqSrKzUzziZ0QlWAG0Yk9IL57zQx9QwZOr/q+9IwZrB/ZZGbwHTHmxYPYzpWvpc5Vt+R08ytmNfA3n1nNntIihvdI4qrvTMUaXe35vV6zHN15xBxfUq96qxEMt5vsA3ZGTJ2NrY32T4nAoNr8Qzh8QbW6f4uIiEiYbDh4hlK3h5TEaIb3CN283k5xDq4c14vX1+cA8IOvDeSbE3qH7PnbAovFwh3npLDqf0so/3QZ3oTxWGOTK7NeSZXzNpPMAKiiFNxlZ30tNQONvR/BkY3UCAAdcWZQd3YWzXfs4pNVgc/p/WZm8dA689YMMcAl1kTsRzPMTGd+TgDLkS1mNjOuqxnox3Xxf92ab+PvWeXYuvXnye9dXfecW6/HDFwPrMS5fTn2w2tJ8DrBixns9RgDPcZCz7Hm164DawZVhmEGshVl5jl3V2Z8y4urbr77Calm9jm5r1mmXX0YXoOr/7aarEP5WPDS23KCoZZDDLAc5RRJbPf2Za/RC9fhKDjs28sD5NdxTqxALDAaduYBzbx40mQ9K2/VrAX4qt49RvRM4r/3nIvdHgU9Rpu3QIjtDP0vMm/NsOA/W9hzvIjUpGj+cetE4qPPCjutVujUy7x1ABEYVJvdv+2o/FtERETCq/qSRKHutP3dC/qzfEceXxuawn3TB4f0uQOurMBsimSPga6DGp5/axhmWeuml7l6y7/5ZlQRVAD/W9i6MaSMgIGXmLc+U/0rzjTKXWZmlU/sNMtuy4vNUnCLBTjra8lpcB6h6PhBKDhMgqWMBG8h5FVlXYlKhG6VJbRdB5kltTZHzWZU/u8LzBLqpF6Q1LPyVhnoJKT6k1Fne/6NL3nPe5TvDx9QfxMrq80MmHuOJWHqD5ny/z6gZ+keHvzWVMaOmdj4HGmLxXx+mwOiW94pesXu42QdygfAwMohI5VDRiqZLT5i27TtqJOPduRx6cjwd7M/eLKYJVuPAfD83In06FTHPPoOJuKCat861Q7DzFCr+7eIiIiEy4rd5nzqC0M0n7q6jG7xrP+/6Y1vGCrOY+Y80IOfmSWn0YlmZjc6seatvMgMoE8fqOwufMDc3ic6yexc3HsS9J4IvSZCQndzm6/+DZte9gehFuBMdG9WlfQhPa6C8ak2M9D0dRIuN0vjsUVVNs6KMctf7bHm1879zFLZgZeYAWlLOGIgbaR5a4JtRwu49tk1lJRXkEQJPSynePjCTpwztI8ZRCekBHV+tsdrsGq3rw9ASpP2sVotTBvcg3ezDD7MS2JsYwF1AC1cnQ3Anef14xeXDW318dxuNx8sXcpll17aZpZyfCJzN8+s2MfC1QfbRFD98ppsDMPsEzG6gc7wHUnEBdW+OQ82f1CtTLWIiIiE3uEzJew9XoTVAucPDH1Q7VeYa2ZunUfNcltPOXjcld+7zbm17jIzwCwvNufgllfeXEXgcWO3WLmktAx79oNVc0YtNjMITu5T+9apt5l1zf7c7Gp88DMzW9sa8d0rx+eEAyvNm0+nPuY8Z4/LvG+LhuFXwPi5FHcax31/XIm3AJbdfkHN9XO95moxZ5cUh0ue01xLvKTcw7kDuzE0NYF/fJ7N49mdefPSaSEZw5YjBZwpcZMYY2d8n+Qm73fRkBTezTrKil0n+PmlrQ9um2LfiSJW7T6BxQJzp2Zgt7U+mDe8VmwWsNusATleINw8tS/PrdrP2v2n2ZnrZGha+JaIK3ZV8O8NhwC4ZVpG2MYRahEcVPsalSlTLSIiIqG3sjLbN75PZzrFtSLj5fWa3ZQPrYVD682MbPVS3upf3aVwdBMc+bKy8/Ims1lQK1mABIDTx2v/8NDaevYwaj/WYzRknG8G3q7COm5OM1vcpR90zjAzxV36mXNpoxPMpZlO7IDDX8DhjXBkg1lSXWDOHSd1pLl+7ehr/Q2VegMzhqfy4bY8Fq0+yG+vGlU1pDYSTAOUlFdwx6IvyHWWMaB7PM/cOIGC4jJe+vwg6w6cCVkw5ZuycN7Abs0KKs8f1A2LBXYcc5LnLCM1KSZYQ/T75xozS33J0BT6dI0L+vOFS49OscwakcqSLbksWp3No1ePanynIHn7yyMUuiro1y2eCweF8WJhiEVsUG31lgPKVIuIiEh4+JbSanbXb1+DrENrIaeyuVVZfssHYrFCtyFVc2+tjqq5rL7v7dFmc6noRPNrVGWn5qhEsDmocJezevVnTJsyGbvVCobHzPKWnjGbZ519qyilRhCdcR70meIPdFvMZjfX0k0bBRNvNx8rKzC7F8ckm4/XURp9y7QMPtyWx9ubjvCzS4fSKbZtlPX6eLwGP3oji61HnHSJj+KlW8+hU6yDODuM6mKw+bQlZMFUS5eA65oQzehendh8uICVu0/wrYnBXfKoyFXBWxvNzmORkDG9ZWoGS7bk8u6XR/jFpUNbd6GuhQzD4OXVBwG4eUpfsxt5hIjAoNp8gVm9mlMtIiIi4VFe4WX13pNAE+allpw2A+fs1ZCz1swwn73ckT0Wek2APpPNjHRhLhQcqblUkrvE3LbLAHPOca/x5te00WaA3AqG282Z+DyM9CnQ2DxTwzC7X9ujzI7YwRbTCfpd0OAmU/t3ZUhqIrvyCvn3hkPceX7/4I+rGX6/dCeZ2/OIslt5fu6EGlnXC9K8bD5tDUkwdaa4nM2H8wG4cHDT5lNXd+GQFDOo3hX8oPo/Gw9T5KpgQPd4zhvYLajP1Rac068LQ9MS2ZlbyL82HOKuC0L/Gl697xR7jhcRF2XjmomRtZpABAbVZidGi+HBihdnWQWGYYS846aIiIhEgLxt5tquvqZbMZ0gJokvj7opKXfTLT6aEV0Ms+lWyWkoPV319cQuyFljdoU+W0IqpE82s7vpU8yMbz2dmgEzkC3LN7PSoQhkG2KxmI3D2hCLxcLcaX35v3e28s+12dx+br82k2V7bV0Of1+1H4A/XjOaCX1rdtsekARDUhPYlVcU9GBq1Z4TGAYMTUskrVPzy7cvGtKdPy/fw6d7TlDh8QZtTrLXa7BozUHAzFJHwud8i8XCrdMy+MXbW3h57UFuP68fthC/hhdWZqm/Ob43STFtq9oj2CIwqK76AzuowOW1Uur2EBcVeadCREREgsDrhd1LYe0zZhOuOkwG9kZbwGPF+gdP48fsNtgMoPtMNW+dM5rX4dliaX1pdQd31bhe/P6DnWSfKmHF7uN8bWhquIfEZ3tO8uv/bgXgvumDuWJs7TV9LRa4eUoffvXf7UEPplbual23+jG9k0mOc5Bf4ibrUD4TM+pZjquVPt17kv0nikmItnP1+MjJmF4xthePfrCTQ6dL+WTncaYPD91r+NDpEpbvMNftvmVa35A9b1sReZFk5ZxqgBirB5fXnFetoFpERERaxVUEWa/Bur/BaTOziMVmLu1UUWY22fIt1+R1Y7MYQGVAbY+FuK4Q1xliu5jfd+plZqH7TIH4jl++Gm5xUXa+NTGdFz47wMLV2WEPqvfkFXL3qxvxeA2uGteLH14ysN5tvzG6B39ctieowZTXa7BqT+V86haUfgPYrBbOH9Sd/202u4AHK6heVJkxvWZCbxKiI+czfmyUjW9PSue5VftZtOZgSIPqV9Zm4zXMBnYDU1q+rnh7FTmvMp9qQXWXaIOCUnNedSg6EIqIiEgHVHAY1j0HmxaZQTOYJdYTboVzvmMuH1XNsfwSLv7dUjpZSvjwR+eR3DUVHLGhH7fUMndqBv/4/ACrdp9g34kiBnRv3VzzljpZ5OL2RV9QWFbBpIzO/O6boxosYY6NsnHdpHT+HsRgattRJyeLyomPsjGhb8urHi4aXBlU7z7OT2YNCeAITdmnivmkskP53KmRlzG9aUpfnv90P5/uOcne44UhCXBLyz288UXkLaNVXdtYXC2ULBa8FnN5hM7R5lIOBaXqAC4iIiLNdHwnvHM3/GkMrP6zGVB3GQCzH4P7tsOM39QKqAFW7j5JGdH0TO9HclqGAuo2pE/XOL5W2TjOtxxTqJW5PXzn5Q0cOl1K365xPHfzRKLtjS/tdfOUvlgsVAZTRQEfl28prXMHdiPK3vIQ4oLKbvdbjzg5UegKyNiqe3lNNoZhdtXvH6aLIuGU3iWOS4aZF1UWrQ7Na/i/WUcoKHXTu3MsXxvasiqG9i7ygmrAazET9MlR5hU/dQAXERGRJstZC699G56ZDJtfA2+FuSzU9W/CvA1wzl0NdtNu8VJaEhK+TNu/NxwK+WdEr9fgp299xaacfJJi7Lx46yS6xEc1viOVwVRlyfrLlU26AmnFbt9SWq0LmronRjOyl7me9qrKYwZKsauCf20wM6a3RmjGFKp+9/9sOowzyK9hwzD8DcrmTu0b8uZobUVkB9XRXkBrVYuIiEgjvF7YtRRevBRenAW7PwAsMOwbcNfHcOv7MORSsDb80crt8fJ5U5fSkrA4b2A3+nePp7jcw38q1zkOlac+2s3/Nh/FbrXw7M0Tml1+ftu5GYC5nFQgLwgUlLj5MucM0PImZdX55mSvCHBQ/c6XRygsqyCja1xEX7SaNqArg1ISKCn38NaG4L6G1x84zc7cQmIc1qAvk9aWRXRQ3anywl+wr+CIiIhIO1V0HD57Cp6eBK9fZy5xZYuC8XPNrPR1/zTXh26iTdlnKHRV0CU+itG9wry0ldTJarX4M30vr8nG6zVC8rz/2XiYP3+8F4BHrh7FtAHNb07nC6aKyz28FcALAp/uPYHXgEEpCfRKbv10BV9g/umeE3gCdH4Nw/Bn6G+emtFmlkQLB3OJuAzArFoI5mvYt3TZVeN6kRzXtKqKjigyg2qruaxWUpQy1SIiInIWrwd2L4M3boQnhsFHD8CpvRCVCOf+CH70FXzjL9Ct/m7M9fFl5s4f1C2iP/S3dVePN7tG7z9ZzKeVlQXBtG7/KX7x9lcA3H3RgBZn/GoGU4G7IOCbsnBRALLUAOPSk0mKsZNf4mbz4fyAHHPNvlPszisiLsrGtRMjZxmt+lw9rheJMXYOniph5Z7AVgT4HM0v5cNtvmW0MoLyHO1FZAbVlY3KOjnM/2g0p1pEREQozIWPfwtPjYLXroWd75vzpXtPMoPoH+80m48l9WjxU6wMcHAiwZEQbeeaCWZg5lueKVgOnizmu69sxO0xuGxkGj+d2bqO2L5g6sDJYv8SWK1hGAYrd/v6AARmyoLdZuX8Qea/AV/A3lq+eb1Xj+9FUowjIMdsz+Kj7Vw7wbw4E6zX8KvrsvF4Dab078LQtKSgPEd7EaFBtVn+negwM9VOdf8WERGJbKf2wXMXwqo/gPMIxHaGKd+Hu9fAnR+Z5d4NNB9riuPOMrYfc2KxwAWDFFS3db7lmD7ZdZzsU8VBeY78knJuX/gF+SVuxvTuxBPfGtvqCoZAB1Pbj5lduuOibEzq1/KltM7mKwFfGYB51YfPlPDRjsqM6dSMVh+vo5g71ewIv2LXCQ6cDOxruMzt4fX1agrnE6FBtXn1KsGuTLWIiEjEy8+BRd+AolzoNhiueRF+vAsufRRShwfsaXyl36N6daJrQnTAjivB0b97AhcO7o5hmKXUgVZe4eV7r2xk/8lieiXH8vwtE4mNanzprKbwBVOfBCCY8mWSpw3o2qSlvZrK10jsq8P5nCpq3dJa/1ybjdeAcwd2ZVBq8Ndlbi8yusVzUeV5DnRH+Pe/Osbp4nJ6doph+rDAr4ve3kRoUG3+h5Bg9wCaUy0iIhKxnEdh0RxwHoaug+DWxTDym2APfNDry8hdFMFdidsbXwbuXxsOUewK3OdFwzD4v3e2sHb/aRKi7fzj1omkJMYE7PiBDKaqSr8D+7pNTYphWI8kDMNcW7ulytwe3vzCzJgqS12bb67zWxsOB+w1bBiGvwripql9sdsiMqSsISLPgNdqln/H+zPVCqpFREQiTtFxM0N95iB0zoBb3oOE4CxzVeHx8qkvONFSWu3GhYO7k9E1jsKyCt758kjAjvu3lfv498bDWC3wlxvGBWU+aiCCKWeZm43Z5lJawVgC7qIAlID/N+sI+SVueneO5RJlTGu5YFB3+nWLp9BVwdubAtMRflNOPluOFBBlt/LtSX0Ccsz2zh7uAYSDr/w7zmZmqrWkloiISIQpOQ0vXwmn9kBSb7jlf5DUs9Zmp4pcHCsoa/XT7TleiLOsgk6xDsamJ7f6eBIaVquFm6dm8PD721m0+mBA/nZbjhTwh6W7AHjwGyO4OEgXWXzB1IGTxby96TA3tyCL+/mek3i8Bv27x5PeJS7gY7xwcHf+tmIfq3afwOs1mj2f3DAMFq42S/PnTu2LTR31a7FaLcyd2peH/redRWuyuWlKXyyW1p0nX5b6ijE96RIfuctoVRehQbVZ/u0LqpWpFhERiSCl+fDPK+H4NkhIMzPUybWzLScKXZz3+49xVXgD9tTnD+qmD/7tzLUTe/P4sl3sOV7E1//yWcCOe+u0DOYGsVw5EMFUsEq/fSb07UxitJ1TxeVsOVLAmGZetPji4Bl2HHMS47C2eBmySHDNhN489uEu9h4v4vO9pzhvUPPXQPc57ixjyZZjgJbRqi4yy78ru3/HWpWpFhERqcvTTz9NRkYGMTExTJ48mfXr1ze4/VNPPcWQIUOIjY0lPT2d++67j7Ky1md4A85VCK9eA8c2Q1w3M6DuOqDOTfedKMJV4cVutZCWFNPqW//u8dx2bkZof19ptaQYBz+ZOYSenVr/GvDdbp7Sl19/PXBN8OpzzYTexEfZ/MFUcxiGUW196uBk0x02K+cONAO8lpSA+zKmV43rRXKcMqb1SYxx8M3KJeIWtrIj/KvrcqjwGkzs25mRvToFYHQdQ4Rmqs3y71ireeW5yFXRopITERGRjujNN99k/vz5PPvss0yePJmnnnqKWbNmsWvXLlJSan+4fu211/jFL37Biy++yLRp09i9eze33norFouFJ554Igy/QQMW/xgOfwExyTD3Xehe/5rABaXmRfdRvTvxzvfPDc34pE26/bx+3H5ev3APo9l8wdTLa7JZuPpgszKUu/IKyXWWEeOwMrlfl6CN8cIh3Vm6LZcVu47zw0sGNXm/YwWlLN2WCyhj2hRzp2bw8ppslu/M49DpkhaV85dXeHltfQ6gc362yMxUW83y72iL+WZpGFBUrhJwERERgCeeeIK77rqL2267jeHDh/Pss88SFxfHiy++WOf2q1ev5txzz+WGG24gIyODmTNncv311zea3Q6LQ+vMr1c+A2mjGtzUF1R3inUEe1QiQeMrMfcFU021sjJLPaV/V2IcgVtK62y+ZmVZh/LJLylv8n6vrs3B4zWY3K9LUBq9dTQDUxI4f1A3DMNcgqwlPth6jBOFLlKTorl0ZFqAR9i+RWim2vy1HVQQZbdSXuGlsKyCpBi9aYqISGQrLy9n48aNLFiwwP+Y1Wpl+vTprFmzps59pk2bxiuvvML69es555xz2L9/P0uWLOHmm2+u93lcLhcuV9XatE6nEwC3243b3bppWb796zqO3V2GBXDHp0Ejz5NfbI4vMdrW6jF1dA2dcwmeppz3vp2jOXdAVz7fd4qFn+/nF5fWX51R3Sc78wA4f2DXoP5du8XZGZySwO7jRazYmcfloxoP1lxuD6+tNwPDmyanh/R1155f6zee05tP95zkzS9ymHdhv2avi/7S5wcA+PbE3uD14PZ6gjHMWsJ5zpv6nBEaVFcGzx43STF2ThaVU1jmBmLDOi4REZFwO3nyJB6Ph9TUmkvTpKamsnPnzjr3ueGGGzh58iTnnXcehmFQUVHB9773PX75y1/W+zyPPvooDz30UK3Hly1bRlxcYLoMZ2Zm1nrsstJCooBVq9dRFNPw8jIbc6yAlfy8oyxZEpilaDq6us65BF9j53243cLn2Hh97UGGuvfRWCxV5oEvDtoAC8aRrSxZsjVwg61Db5uV3Vh57ZMsLIcabwy4/oSF08U2kqMM3Ac3sqRliddWaY+vda8BXaNtnCqt4LevLmNaqtHkfbOLIOuQHZvFoFvBLpYs2RXEkdYtHOe8pKRp1R0RGlRX/k9S4SIxxsHJonKcpSr/FhERaYkVK1bwyCOP8MwzzzB58mT27t3Lj370Ix5++GF+/etf17nPggULmD9/vv++0+kkPT2dmTNnkpTUulJOt9tNZmYmM2bMwOGoWYVm32qABy742kxI7tvgcTa8vwOOHGLk0AHMnt70uZ6RqKFzLsHT1PM+y2vwwVOfcfhMKa4eo7lyYu8Gj5u5/Tie9Vn06RLLLd88P9DDrqXz/lN8/NJG9pfGcOmlFzbY58gwDF54bh3g5I4LBjHnwv5BH1917f21npd8kN8t3U1WcScevmxqkzvC//StLcAxvj66J9++suGpM4EWznPuq6JqTEQG1UZl+TceN4kx5veF6gAuIiJCt27dsNls5OXl1Xg8Ly+PtLS6yzJ//etfc/PNN3PnnXcCMGrUKIqLi/nOd77D//3f/2G11m7hEh0dTXR0dK3HHQ5HwD401TqWYUCF2ZHcEZMAjTxPocssbewSH9MuPzyHQyD/ftJ0jZ13B3DL1Ax+u2QHr6w7xI1TMhoMpj7bfxqAi4ekhOTvOWVACvFRNk4WlbPnZGmDXaU35ZxhyxEnUXYrN07tF7bXW3t9rV9/TgZ/Wr6PXXlFbDpcyJT+XRvd52SRiyVbzfeE287rH1HnvKnPF5GNyjxWX/l3uX8etdaqFhERgaioKCZMmMDy5cv9j3m9XpYvX87UqVPr3KekpKRW4GyzmVVhhtH08sKg81aAUVlaaq8d0J/NWfnZQI3KpCP41sR0Yh02duYWsu7A6Xq3MwzD36QsWEtpnS3KbmVaE5fW8i2j9Y0xPekSr2W0mqtTnIMrx/UCqs5lY15fl0O5x8uY9GTGNnMt8UgRkUF1Vaba5c9Ua61qERER0/z583n++edZtGgRO3bs4O6776a4uJjbbrsNgLlz59ZoZDZnzhz+9re/8cYbb3DgwAEyMzP59a9/zZw5c/zBdZtQUW3dbHtMo5v7un8nKaiWDqCpwdTe40UcyS8lym5tUhYzUC4cbHYBX7HreL3bHHeWsWTLMQBu1ZJOLXbLNHPqy7LteRzNL21wW7fHyyvrzEnrt05reMpMJIvI8m//nOoa5d/KVIuIiABcd911nDhxgvvvv5/c3FzGjh3L0qVL/c3LcnJyamSmf/WrX2GxWPjVr37FkSNH6N69O3PmzOG3v/1tuH6FulVUdRvH1nimWktqSUdzy7S+vL4+xx9M9Uyu3aTXlyme3K9Ls7tDt4Zvaa1NOfkUlLrr/Hf36roc3B6DCX07N1giLg0bmpbElP5dWLv/NK+szeZnlw6td9sPt+WS53TRLSGK2aN6hHCU7UuzMtWPPvookyZNIjExkZSUFK688kp27Wq889u///1vhg4dSkxMDKNGjWLJkiUtHnAgVHX/rir/VqZaRESkyrx588jOzsblcrFu3TomT57s/9mKFStYuHCh/77dbueBBx5g7969lJaWkpOTw9NPP01ycnLoB94QX6baFgV1zPM+W1WmOiJzENIB+YIpj9fglXrWKl4R4tJvn96d4xiYkoDHa/D53pO1fl5e4eW19TkA3KIsdav5Mv1vfHGIMnf9S2P5qhpuOKcP0fY2VHnUxjQrqF65ciX33HMPa9euJTMzE7fbzcyZMykuLq53n9WrV3P99ddzxx138OWXX3LllVdy5ZVXsnVrcFvzN8RrrXxzrOz+DcpUi4iIdHi+THUTSr9BmWrpmBoKpopdFayvnG/tK8cOpYZKwD/YeowThS5SEqO5bGTja1lLw6YPS6VnpxhOF5fzv81H69xm29ECvjh4BrvVwo1TVPrdkGYF1UuXLuXWW29lxIgRjBkzhoULF5KTk8PGjRvr3edPf/oTl156KT/96U8ZNmwYDz/8MOPHj+evf/1rqwffUnWVfztLlakWERHp0HyZ6iY0KStzeyivMJuaKaiWjqShYGrt/lOUe7z07hzLgO7xIR+brwR85e4TtZocLqzMmN44uS8OW0S2hQoou83KTVPNQHnRmoN1NpX0ZakvHZlGalLTLkZGqla9IgsKCgDo0qVLvdusWbOG6dOn13hs1qxZrFmzpjVP3So1yr9jlakWERGJCP6guvEPh76L7VYLJESr/Fs6joaCqarS7+5NXr84kCZldCHWYSPP6WJnbqH/8a8O5/NlTj4Om4XrJ6eHfFwd1bcn9SHKbmXrESebcs7U+NmZ4nL+m2VedFFTuMa1+F3C6/Vy7733cu655zJy5Mh6t8vNzfU3NvFJTU0lNze33n1cLhcuV1UzEd+i2263G7e7dRllt9uNt7L7t7eijDi7+R+Gs7S81ceWuvnOq85v6Oich57OeXiE67zr79xO+cu/m96kLCnWEZbgQiSYvj2pD099tMcfTE3o2wXDMFix2yy7vmhwaOdT+8Q4bEwd0JWPdx5nxa4TDOuRBFRlqS8f1YOURGVMA6VLfBRXjOnJvzce5qXPDzKhb1Wi9I0vDuGq8DKiZxIT+nYO4yjbhxYH1ffccw9bt27ls88+C+R4ALMh2kMPPVTr8WXLlhEXF9fq46dVln/nnzzO9s0bARtHT+aHvYFaR5eZmRnuIUQcnfPQ0zkPj1Cf95KSkpA+nwRIMzLVmk8tHVn1YGrh6mwm9O3CgZPFHDpdSpTNytQBoVtK62wXDenOxzuPs3L3ce6+aAAni1y8v9lcRksNygLvlmkZ/HvjYZZuzSXPWUZqUgwVHq+/kd0t0zJ0YbEJWhRUz5s3j/fff59Vq1bRu3fvBrdNS0sjLy+vxmN5eXmkpdXfYGDBggXMnz/ff9/pdJKens7MmTNJSkpqyZD93G43m//zFQCdk+KZfuG5/HX7WrDHMHv2ha06ttTN7XaTmZnJjBkzcDj04SQUdM5DT+c8PMJ13n0VVNLONCNT7VsVREG1dFS+YOqDLcfIu3yYv/R7Ur/OxIdxyoOZJd/GhoNnKCxz88b6HMo9Xsb07sS4PsqYBtrIXp2Y2LczG7LP8OrabObPHMJHO45zJL+UznEOvjGmZ7iH2C4061+MYRj84Ac/4J133mHFihX069ev0X2mTp3K8uXLuffee/2PZWZmMnXq1Hr3iY6OJjq69huew+EIyIcmX/m3xeOmS4K5Pl+hq0IfhIMsUH8/aTqd89DTOQ+PUJ93/Y3bKWWqRfxqBFPrcsg6lA+Er/Tbp0/XOPp1i+fAyWJW7T7JK2u1jFaw3TItgw3ZZ3htfQ73fG2gv0HZt8/pQ4xDy2g1RbMald1zzz288sorvPbaayQmJpKbm0tubi6lpaX+bebOncuCBQv893/0ox+xdOlSHn/8cXbu3MmDDz7Ihg0bmDdvXuB+i2aq6v5d7u/+XVLuwe3xhm1MIiIiEmTNmVNdUjmnOkZBtXRcvkD1tXXZrNt/CoALh4R+Ka2z+ZbWemTJDnKdZXRLiOLy0T3CPKqOy+zuHc3JonKe+mgPa/afwmqBm7SMVpM1K6j+29/+RkFBARdddBE9evTw3958803/Njk5ORw7dsx/f9q0abz22mv8/e9/Z8yYMbz11lu8++67DTY3C7bq3b8TYqqS9UXqAC4iItJxNStTbX4mSFKmWjqw6sGUq8JLz04xDEpJCPew/EtrHck3E3fXn9OHaLsypsHisFm5cbIZQP9txT4AZg5Po1dybDiH1a40u/y7MStWrKj12LXXXsu1117bnKcKKl/5N55yHDYrcVE2Sso9FJZV0Dk+KryDExERkeBoQfdvlX9LR+YLpp7I3A3AhUNS2kRTqin9uxJtt+Kq8GK3WvwBnwTP9ef04a8f76W8snJX5fbNE5Erp3utVUE14C8B9zUlERERkQ6oOetUq1GZRIjrz+lDlM0MCXxl1+EW47Axpb/ZgXzWyDTSOmkZrWDrnhjtL7EfkprIlP5dGtlDqgtfa78w8meqK3xBtYM8p0tBtYiISEemTLVILd0To3n4yhFsOVLAJcPC26Ssuh/PHExCjJ1fXDo03EOJGD+ZNQRXhYfbz+3XJioW2pPIDqrPylQXak61iIhIx9WC7t9JsRH5UUkizHWT+nDdpHCPoqbRvZN5+obx4R5GROmVHMszN04I9zDapcgs//YF1V43GIa/s6eCahERkQ6sOetUK1MtIiJNFJlBtbXaVedqy2r53kBFRESkA2rOnGoF1SIi0kSRGVRbzg6qlakWERHp8PxBteZUi4hI4Cio9rj986UK1ahMRESk4/KXfzecqXZ7vBSXewD8U8RERETqE5FBNRYrhqVyAfkKl+ZUi4iIRIImZqqrTwdLUqZaREQaEZlBNYAtyvxafU61MtUiIiIdVxMz1c7Ki+yJ0XZsVi0rIyIiDYvcoNruC6rdylSLiIhEgiY2KqtaTktZahERaVzkBtX+TLWr2jrVylSLiIh0WE1cUktNykREpDkiN6i2Vr5RVuv+7VSmWkREpONqdqba3uB2IiIiEMlBte8qtcetTLWIiEgkUKZaRESCIHKDalvlG2WFyz9nSplqERGRDqyJmWqngmoREWmGyA2qrbW7f5dXeClze8I4KBEREQmaJmaqFVSLiEhzRGxQbVTr/p0QZcdSuWKGOoCLiIh0UM2dUx2joFpERBoXsUF19e7fVquFhGjNqxYREenQmjunOk5BtYiINC6Cg2pf9++aV6OVqRYREemADKPpc6rLVP4tIiJNF8FBta/7dzmAf161U5lqERGRjsdbAYbX/L6JmeokBdUiItIEERxUV3X/Bqotq6VMtYiISIfjy1KD5lSLiEhARXBQXdWoDKqXfytTLSIi0uH45lNDVbVaPQpKVP4tIiJNp6D67PLvUmWqRUREOhxfptoWBdb6P/54vQaFLvOzgIJqERFpCgXVHl/5tzLVIiIiHZa/83fDpd+FrgoMw/xeQbWIiDRFxAbVxtndv2N9jcqUqRYREelw/J2/Gy79dlbOp4512IiyR+zHJBERaYbIfbeo1f1bS2qJiIh0WE1cTquq87c92CMSEZEOIoKD6rq7f2tJLRERkQ7IX/7dtOW0VPotIiJNFcFBtbp/i4iIRIwmZqqdCqpFRKSZFFSf1f1b5d8iIiIdkDLVIiISJAqqz5pTrfJvERGRDqi5c6pjFFSLiEjTRG5Qba8ZVCcpUy0iItJxNTNTnaRMtYiINFHkBtXWyqC68k3W9+ZZWFaB4VugUkRERDqGZmaqVf4tIiJNFbFB9dnrVPvmVHu8BqVuT7iGJSIiIsHQxEy1s7JiTUG1iIg0VcQG1f431cry71iHDZvVAoCzVCXgIiIiHYoy1SIiEiSRG1T7M9VmUG2xWKrNq1azMhERkQ5Fc6pFRCRIIjeottZsVAbVO4ArUy0iItKhaJ1qEREJksgNqu11BdVmplrLaomIiHQwTZ1TraBaRESaKXKDat861RW1g2otqyUiItLBNCFTbRiG5lSLiEizRXBQXXNONUBSjG9ZLWWqRUREOhR/UF1/prqk3EOF11xWMynWHopRiYhIBxDBQXXN7t9QbU61un+LiIh0LP7y7/oz1b4stcNmIdZhC8WoRESkA4jYoNqoI1OdqO7fIiIiHVMTMtXVS78tFksoRiUiIh1AxAbV/jnV1cu/Y33l38pUi4iIdChNyFQ7tZyWiIi0gIJqT1VWWutUi4iIdFBNaFSmJmUiItISCqp9V66pvqSWMtUiIiIdShOW1PIF1b7GpSIiIk0RwUF1tTnVhtnpM1Hdv0VERDomZapFRCRIIjio9l2pNsDrAaovqaVMtYiISIfShEy1r1JNQbWIiDRHBAfV1d4wPeYbrb/8u1SZahERkQ6lCZlqpzLVIiLSAhEcVEdVfV/ZAbxqSS1lqkVERDqU5sypjrWHYkQiItJBRG5QbbUDlWtQemouoVFUXoHXa4RpYCIiIhJwmlMtIiJBErlBtcVSqwO4L1NtGGZgLSIiIh1EMzLVCqpFRKQ5IjeohmprVZvl39F2G1F285RoXrWIiESyp59+moyMDGJiYpg8eTLr169vcPv8/HzuueceevToQXR0NIMHD2bJkiUhGm0jDKNZc6qTFFSLiEgzRPakIXsUlOMv/wazA/jJIpfmVYuISMR68803mT9/Ps8++yyTJ0/mqaeeYtasWezatYuUlJRa25eXlzNjxgxSUlJ466236NWrF9nZ2SQnJ4d+8HXxVoDhNb/XOtUiIhJgkR1U+zPVLv9DSTF2BdUiIhLRnnjiCe666y5uu+02AJ599lkWL17Miy++yC9+8Yta27/44oucPn2a1atX43CYAWlGRkYoh9wwX5YaNKdaREQCLsKD6so3zWqZai2rJSIikay8vJyNGzeyYMEC/2NWq5Xp06ezZs2aOvd57733mDp1Kvfccw///e9/6d69OzfccAM///nPsdlsde7jcrlwuaouajudTgDcbjdud+veg337+49TWoQvTHYbVqjj+C63B1eFmc2Od9DqMUSaWudcQkLnPfR0zkMvnOe8qc8Z4UF1ZQlY5ZxqgMTKkq9Cl/6hiIhI5Dl58iQej4fU1NQaj6emprJz584699m/fz8ff/wxN954I0uWLGHv3r18//vfx+1288ADD9S5z6OPPspDDz1U6/Fly5YRFxfX+l8EyMzMBCCm/BSzAI/FzpIPlta5rbMcwI4Fg5XLM7FaAjKEiOM75xJaOu+hp3MeeuE45yUlJU3aLsKD6prdv6FqbUqVf4uIiDSN1+slJSWFv//979hsNiZMmMCRI0f44x//WG9QvWDBAubPn++/73Q6SU9PZ+bMmSQlJbVqPG63m8zMTGbMmGGWo5/eB9vAGhXL7Nmz69xn7/Ei2LiaTrFRfP3yi1v1/JGo1jmXkNB5Dz2d89AL5zn3VVE1JsKD6jrKv6PNx1T+LSIikahbt27YbDby8vJqPJ6Xl0daWlqd+/To0QOHw1Gj1HvYsGHk5uZSXl5OVFRUrX2io6OJjq7dNMzhcATsQ1PVsTwAWOwx9R67pMIAzM7f+qDccoH8+0nT6byHns556IXjnDf1+SJ7SS17XeXfylSLiEjkioqKYsKECSxfvtz/mNfrZfny5UydOrXOfc4991z27t2L1+v1P7Z792569OhRZ0Adck1YTktNykREpKUiO6iuq/t35ZupU0G1iIhEqPnz5/P888+zaNEiduzYwd13301xcbG/G/jcuXNrNDK7++67OX36ND/60Y/YvXs3ixcv5pFHHuGee+4J169Qk2+aVwPLaTlLzfd9BdUiItJcEV7+7Quqa3f/LixT+beIiESm6667jhMnTnD//feTm5vL2LFjWbp0qb95WU5ODlZr1XX59PR0PvzwQ+677z5Gjx5Nr169+NGPfsTPf/7zcP0KNSlTLSIiQaSgGmo0KvN1/1amWkREItm8efOYN29enT9bsWJFrcemTp3K2rVrgzyqFmpCptoXVPsaloqIiDRVhJd/+xqV1TWnWplqERGRDqEZmeokZapFRKSZIjuo9jcqqwqgk3zrVCtTLSIi0jE0I1Ot8m8REWmuZgfVq1atYs6cOfTs2ROLxcK7777b4PYrVqzAYrHUuuXm5rZ0zIFTR6MyX6ZaS2qJiIh0EE3IVDsVVIuISAs1O6guLi5mzJgxPP30083ab9euXRw7dsx/S0lJae5TB14d61QrUy0iItLBKFMtIiJB1OxuHJdddhmXXXZZs58oJSWF5OTkZu8XVLba61T7GpSUuj24PV4ctsiukBcREWn3mjOnOkZBtYiINE/IWlyOHTsWl8vFyJEjefDBBzn33HPr3dblcuFyVZVkO51OANxuN25368qyffu73W6sFhs2wFNeirfy8Wir4d/2TFEpneOiWvV8UvOcS2jonIeeznl4hOu86+/czjRpnWplqkVEpGWCHlT36NGDZ599lokTJ+JyuXjhhRe46KKLWLduHePHj69zn0cffZSHHnqo1uPLli0jLi4uIOPKzMxk2NFDDAYO7tvNVtcS/8+irDbKvRb+t/QjutV/UVuaKTMzM9xDiDg656Gncx4eoT7vJSUlIX0+aaWmzKmunPaloFpERJor6EH1kCFDGDJkiP/+tGnT2LdvH08++ST//Oc/69xnwYIFzJ8/33/f6XSSnp7OzJkzSUpKatV43G43mZmZzJgxg+g1WyHvf2Sk96LPZbP92zyybSV5ThcTppzH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5HI51q9fD5VKhcDAQCxatAhz587FO++8A6mUg1uIiIiMhW09kWXgXw2RhQoODkZ4eDiCgoIwfvx4rFu3Djdu3Ki1/MmTJ3Hu3DnY29vDzs4OdnZ2cHJyQmlpKc6fP29wXpVKpf85LCwMRUVFuHTpUrO+HiIiIjLEtp7IMrCnmshCyWQyxMTE4MCBA9i+fTvWrFmDN998E/Hx8TWWLyoqQu/evfHtt99WO+bq6trc4RIREdF9YltPZBmYVBNZMIlEggEDBmDAgAGYP38+OnTogE2bNkEul6OystKgbK9evfDjjz/Czc0NarW61nOePHkSJSUlUCqVAIBDhw7Bzs4O3t7ezfpaiIiIqDq29UTmj8O/iSxUfHw83n//fRw9ehTp6en49ddfce3aNXTt2hU+Pj44deoUkpOTkZOTA41Gg0mTJsHFxQVjxozB3r17kZqairi4OPzv//4vLl++rD9veXk5nn32WSQkJGDr1q1YsGABZs2axTlWRERERsa2nsgysKeayEKp1Wrs2bMHK1euREFBATp06IDly5dj+PDh6NOnD+Li4tCnTx8UFRVh165dGDx4MPbs2YNXX30VjzzyCAoLC+Hl5YXw8HCDq9nh4eEICAjAoEGDUFZWhokTJ2LhwoWme6FEREStFNt6IssgEUIIUwdBROYhOjoaeXl52Lx5s6lDISIiombAtp6o6XGMBxEREREREVEDMakmIiIiIiIiaiAO/yYiIiIiIiJqIPZUExERERERETUQk2oiIiIiIiKiBmJSTURERERERNRATKqJiIiIiIiIGohJNREREREREVEDMakmIiIiIiIiaiAm1UREREREREQNxKSaiIiIiIiIqIGYVBMRERERERE10P8HTzbJPxlNtukAAAAASUVORK5CYII=\n"
          },
          "metadata": {}
        }
      ],
      "execution_count": 12
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-17T03:09:26.718583Z",
          "start_time": "2025-01-17T03:09:25.798787Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "mph2kLCjhjMY",
        "outputId": "a7205c8f-9e39-4ddc-ee23-a05a9326d34d"
      },
      "source": [
        "# dataload for evaluating\n",
        "#推理时alphadropout的p值是0，通过加dropout，一定程度解决了过拟合\n",
        "# load checkpoints\n",
        "model.load_state_dict(torch.load(\"./best.ckpt\", weights_only=True,map_location=\"cpu\"))\n",
        "\n",
        "model.eval()\n",
        "loss, acc = evaluating(model, val_loader, loss_fct)\n",
        "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "loss:     0.3365\n",
            "accuracy: 0.8858\n"
          ]
        }
      ],
      "execution_count": 14
    },
    {
      "cell_type": "code",
      "source": [],
      "metadata": {
        "id": "AkgX_hHLqzFR"
      },
      "execution_count": null,
      "outputs": []
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.8"
    },
    "orig_nbformat": 4,
    "colab": {
      "provenance": [],
      "gpuType": "T4"
    },
    "accelerator": "GPU",
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "754aec9e3b8f4599af03b992b8f4a647": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HBoxModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HBoxModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HBoxView",
            "box_style": "",
            "children": [
              "IPY_MODEL_1acb17a0acd5483c8dfbcc522b9eb610",
              "IPY_MODEL_078907447bb14f2e99b6eabd92328421",
              "IPY_MODEL_58d4ff0313c64a86872b5ebde5506603"
            ],
            "layout": "IPY_MODEL_d4b7a7c89c174a9a8fc82aa2a13de84a"
          }
        },
        "1acb17a0acd5483c8dfbcc522b9eb610": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_c80769781adc48538f482b9a739bcf5f",
            "placeholder": "​",
            "style": "IPY_MODEL_8bf51169fcc94d67adea09f826735702",
            "value": " 55%"
          }
        },
        "078907447bb14f2e99b6eabd92328421": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "FloatProgressModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "FloatProgressModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "ProgressView",
            "bar_style": "danger",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_a14135c169cc447c9b55ab6f3001c577",
            "max": 375000,
            "min": 0,
            "orientation": "horizontal",
            "style": "IPY_MODEL_6d159ae46c8a484db9a0bb2f04654b07",
            "value": 206250
          }
        },
        "58d4ff0313c64a86872b5ebde5506603": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "HTMLModel",
          "model_module_version": "1.5.0",
          "state": {
            "_dom_classes": [],
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "HTMLModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/controls",
            "_view_module_version": "1.5.0",
            "_view_name": "HTMLView",
            "description": "",
            "description_tooltip": null,
            "layout": "IPY_MODEL_2d993a4cc36a44ca95f6c6e5ce83c6a5",
            "placeholder": "​",
            "style": "IPY_MODEL_5c46479c2fbd4faa98d099c738227cfa",
            "value": " 206250/375000 [36:15&lt;26:48, 104.92it/s, epoch=54]"
          }
        },
        "d4b7a7c89c174a9a8fc82aa2a13de84a": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "c80769781adc48538f482b9a739bcf5f": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "8bf51169fcc94d67adea09f826735702": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        },
        "a14135c169cc447c9b55ab6f3001c577": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "6d159ae46c8a484db9a0bb2f04654b07": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "ProgressStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "ProgressStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "bar_color": null,
            "description_width": ""
          }
        },
        "2d993a4cc36a44ca95f6c6e5ce83c6a5": {
          "model_module": "@jupyter-widgets/base",
          "model_name": "LayoutModel",
          "model_module_version": "1.2.0",
          "state": {
            "_model_module": "@jupyter-widgets/base",
            "_model_module_version": "1.2.0",
            "_model_name": "LayoutModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "LayoutView",
            "align_content": null,
            "align_items": null,
            "align_self": null,
            "border": null,
            "bottom": null,
            "display": null,
            "flex": null,
            "flex_flow": null,
            "grid_area": null,
            "grid_auto_columns": null,
            "grid_auto_flow": null,
            "grid_auto_rows": null,
            "grid_column": null,
            "grid_gap": null,
            "grid_row": null,
            "grid_template_areas": null,
            "grid_template_columns": null,
            "grid_template_rows": null,
            "height": null,
            "justify_content": null,
            "justify_items": null,
            "left": null,
            "margin": null,
            "max_height": null,
            "max_width": null,
            "min_height": null,
            "min_width": null,
            "object_fit": null,
            "object_position": null,
            "order": null,
            "overflow": null,
            "overflow_x": null,
            "overflow_y": null,
            "padding": null,
            "right": null,
            "top": null,
            "visibility": null,
            "width": null
          }
        },
        "5c46479c2fbd4faa98d099c738227cfa": {
          "model_module": "@jupyter-widgets/controls",
          "model_name": "DescriptionStyleModel",
          "model_module_version": "1.5.0",
          "state": {
            "_model_module": "@jupyter-widgets/controls",
            "_model_module_version": "1.5.0",
            "_model_name": "DescriptionStyleModel",
            "_view_count": null,
            "_view_module": "@jupyter-widgets/base",
            "_view_module_version": "1.2.0",
            "_view_name": "StyleView",
            "description_width": ""
          }
        }
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}